package com.pingao.mp.handle;

import com.alibaba.fastjson.JSON;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.pingao.mp.modular.sys.entity.User;
import com.pingao.mp.modular.sys.service.MenuService;
import com.pingao.mp.modular.sys.service.UserService;
import com.pingao.mp.utils.Constant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;

public class AuthenticationInterceptor implements HandlerInterceptor {
    @Autowired
    UserService userService;

    @Autowired
    MenuService menuService;
    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 解决OPTIONS “预检请求” 出错的问题
        String method = request.getMethod();
        if (method != null && method.equals("OPTIONS")) {
            return true;//对 预检请求 都放过
        }
        String token = request.getHeader("token");// 从 http 请求头中取出 token
        if (token == null || token.isEmpty()) {
            //throw new RuntimeException("无token，请登录401");
            throw new MpException(Constant.MpExceptionNoneToken, 401, "无token，请登录401");
        }
        // 获取 token 中的 user id
        String userId;
        try {
            userId = JWT.decode(token).getAudience().get(0);
            String userName = JWT.decode(token).getClaim("userName").asString();//获取用户名

        } catch (JWTDecodeException j) {
//            throw new RuntimeException("登录失效，请重新登录401");
            throw new MpException(Constant.MpExceptionNoneLogin, 401, "登录失效，请重新登录401");
        }
        User user = userService.getById(userId);
        if (user == null) {
//            throw new RuntimeException("用户不存在，请检查用户和密码是否正确401");
            throw new MpException(Constant.MpExceptionNoneUser, 401, "用户不存在，请检查用户和密码是否正确401");
        }
        // 验证 token
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
        try {
            jwtVerifier.verify(token);
            //判断权限,以后把他修改成只判断到控制器
            String servletPath = request.getServletPath();
            if (servletPath.equals("/sys/menu/getMenu")) {
                return true;//对于请求菜单的URL不判断其权限
            }
            String n = servletPath.substring(0, servletPath.indexOf("/", servletPath.indexOf("/", servletPath.indexOf("/") + 1) + 1));//截取从开始到第三个/之前的字符串 /sys/menu/getMenu
            //String userMenusStr = JWT.decode(token).getClaim("userMenus").asString();//取出用户菜单权限（准备把他放到redis数据库中，根据用户ID获取）
            String userMenusStr = stringRedisTemplate.opsForValue().get("faraes:mp:userMenus:" + token);
            if (userMenusStr == null || userMenusStr.length() < 1) {
                throw new MpException(Constant.MpExceptionNoneToken, 401, "获取不到用户菜单");
            }
            List<String> list = JSON.parseArray(userMenusStr, String.class);
            List<String> l = new ArrayList<>();
            for (String s : list) {
                String c = s.substring(0, s.indexOf("/", s.indexOf("/", s.indexOf("/", s.indexOf("/") + 1) + 1)));//截取从开始到第三个/之前的字符串
                l.add(c);
            }
            //权限只判断到控制器
            if (!l.contains(n)) {
//                throw new RuntimeException("您没有权限访问该接口402");
                throw new MpException(Constant.MpExceptionNoneUser, 402, "您没有权限访问该接口402");
            }
        } catch (JWTVerificationException e) {
//            throw new RuntimeException("登录失效，请重新登录401");
            throw new MpException(Constant.MpExceptionNoneUser, 401, "登录失效，请重新登录401");
        }
        return true;
    }
}
